package e.odbo.data.util.en;

import e.odbo.data.OdbOContent;
import e.odbo.data.model.*;
import e.odbo.data.util.ClassUtils;
import e.odbo.data.util.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;

public class DatabaseUtils {

    //resource
    public static void printBuildI18n(DataBase dataBase,String prefix,String temp){
        StringBuilder beanBuilder=new StringBuilder();
        buildI18nUseColumnComment(dataBase,beanBuilder,prefix,temp);
        System.out.print(beanBuilder.toString());
    }
    public static void printBuildI18nWithJava(DataBase dataBase,String prefix){
        printBuildI18n(dataBase,prefix,"%s = %s");
    }

    public static void printBuildI18nWithAndroid(DataBase table,String prefix){
        printBuildI18n(table,prefix,"<string name=\"%s\">%s</string>");
    }

    public static void printBuildI18nWithJavaScript(DataBase dataBase,String prefix){
        printBuildI18n(dataBase,prefix,"%s = '%s'");
    }

    public static void printBuildI18nJson(DataBase dataBase){
        StringBuilder beanBuilder=new StringBuilder();
        buildI18nJsonUseColumnComment(dataBase,beanBuilder,"%s : '%s'");
        System.out.print(beanBuilder.toString());
    }

    public static void buildI18nUseColumnComment(DataBase dataBase, StringBuilder i18nBuilder, String prefix, String tempString){
        if(prefix!=null&&!prefix.isEmpty())
            prefix=ClassUtils.getI18NString(prefix,dataBase.getName());
        else
            prefix=dataBase.getName();
        i18nBuilder.append(String.format(tempString, ClassUtils.getI18NString(prefix,"name"), dataBase.getName())+"\n");
        i18nBuilder.append(String.format(tempString, ClassUtils.getI18NString(prefix,"ver"), dataBase.getVersion())+"\n");
        for(Table table:dataBase.getTables())
            TableUtils.buildI18nUseColumnComment(table,i18nBuilder,prefix,tempString);
    }

    public static void buildI18nJsonUseColumnComment(DataBase dataBase, StringBuilder i18nBuilder,String tempString){
        i18nBuilder.append(dataBase.getName()+":{\n");
        i18nBuilder.append("\t"+String.format(tempString, "dataBase_ver", dataBase.getVersion())+",\n");
        List<Table> tables=dataBase.getTables();
        for(int i=0;i<tables.size();i++) {
            TableUtils.buildI18nJsonUseColumnComment(tables.get(i), i18nBuilder, tempString);
            if(i<tables.size()-1)
                i18nBuilder.append(",");
            i18nBuilder.append("\n");
        }
        i18nBuilder.append("}\n");
    }

    // Makedown
    public static void printMakedownDoc(DataBase dataBase){
        StringBuilder mdDocBuilder=new StringBuilder();
        buildMakedownDoc(dataBase,mdDocBuilder);
        System.out.print(mdDocBuilder.toString());
    }



    public static void buildMakedownDoc(DataBase dataBase, StringBuilder mdDocBuilder){
        List<Table> tables=dataBase.getTables();
        mdDocBuilder.append("# &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;自动生成数据库结构     \n\n");
        mdDocBuilder.append("> Database name："+dataBase.getName()+"( ver:"+dataBase.getVersion()+" )   \n\n");

        mdDocBuilder.append(">>>    total : "+dataBase.getTables().size()+" tables, subMode:"+dataBase.isSubModel()+"   \n\n");

        String tableComment=null;
        for(int i=0;i<tables.size();i++){
            //if(i>0&&i%3==0)
                //mdDocBuilder.append("\n\n");
            tableComment=tables.get(i).getComment();
            String ref=tableComment==null?tables.get(i).getName():tables.get(i).getName()+"("+tableComment+")";
            mdDocBuilder.append(String.format(" %d. [%-15s--------------------------------------%s](#%s) \n ",i+1,tables.get(i).getName(),tableComment==null?tables.get(i).getName():tableComment,ref));
        }
        mdDocBuilder.append("\n\n");
        if(tables.size()<10)
            mdDocBuilder.append(OdbOContent.ICON);

        mdDocBuilder.append("\n------\n");
        for(Table table:dataBase.getTables())
            TableUtils.buildTableStruct(table,mdDocBuilder);

        buildMakedownDoc(dataBase.getAddData(),mdDocBuilder);

        buildMakedownDoc(dataBase.getMigrations(),mdDocBuilder);
    }

    public static void buildMakedownDoc(Collection<Migration> migrations, StringBuilder mdDocBuilder){
          for(Migration migration:migrations)
              buildMakedownDoc(migration,mdDocBuilder);
    }

    public static void buildMakedownDoc(Migration migration, StringBuilder mdDocBuilder){
        mdDocBuilder.append(String.format(">>migration ver from: %s  to: %s\n",migration.getOldVersion(),migration.getCurrentVersion()));

        if(migration.getAddTable().size()>0) {
            mdDocBuilder.append("add tables:\n\n");
            for (Table table : migration.getAddTable())
                TableUtils.buildTableStruct(table,mdDocBuilder);
            mdDocBuilder.append("\n");
        }

        if(migration.getRemoveTable().size()>0){
            mdDocBuilder.append("remove tables:\n");
            for(String tableName:migration.getRemoveTable())
                mdDocBuilder.append("\t"+tableName);
            mdDocBuilder.append("\n");
        }

        if(migration.getAddTable().size()>0) {
            mdDocBuilder.append(("add datas:\n\n"));
            buildMakedownDoc(migration.getAddData(),mdDocBuilder);
        }

        if(migration.getRemoveData().size()>0){
            mdDocBuilder.append(("remove datas:\n\n"));
            buildMakedownDoc(migration.getRemoveData(),mdDocBuilder);
            mdDocBuilder.append("\n");
        }

        if(migration.getAddForeignKeys().size()>0){
            mdDocBuilder.append("add Foreign Keys:\n");
            for(TableForeignKey foreignKey:migration.getAddForeignKeys())
                TableUtils.buildTableStruct(foreignKey,mdDocBuilder);
            mdDocBuilder.append("\n");
        }

        if(migration.getRemoveForeignKeys().size()>0){
            mdDocBuilder.append("remove Foreign Keys:\n");
            for(Map.Entry<String,String[]> foreignKey:migration.getRemoveForeignKeys().entrySet())
                mdDocBuilder.append(String.format("%s:%s(%s)\n",TableUtils.buildNameKey(foreignKey.getKey(),foreignKey.getValue()),foreignKey.getKey(),StringUtils.join(foreignKey.getValue(),',')));
            mdDocBuilder.append("\n");
        }

        if(migration.getAddColumn().size()>0){
            mdDocBuilder.append("add table columns:\n\n");
            StringBuilder memoBuilder=null;
            for(Map.Entry<String, Column[]> entry:migration.getAddColumn().entrySet()) {
                memoBuilder=new StringBuilder("MEMO:    ~:Forerign Key; A:AUTO INC; N:NOT NULL\n\n");
                mdDocBuilder.append(String.format(">> add column to [%s](#%s)\n\n",entry.getKey(),entry.getKey()));
                Column[] columns=entry.getValue();
                TableUtils.buildTableStruct( columns, mdDocBuilder, memoBuilder);
                mdDocBuilder.append(memoBuilder);
                mdDocBuilder.append("\n-------\n");
            }
        }

        if(migration.getRemoveColumn().size()>0){
            mdDocBuilder.append("reomve table columns:\n");
            for(Map.Entry<String, String[]> entry:migration.getRemoveColumn().entrySet()) {
                mdDocBuilder.append(String.format(">> remove column(*s) from [%s](#%s)\n\n",StringUtils.join(entry.getValue(),','),entry.getKey(),entry.getKey()));
                mdDocBuilder.append("\n-------\n");
            }
        }

        if(migration.getAlterColumn().size()>0){
            mdDocBuilder.append("alter table columns:\n");
            StringBuilder memoBuilder=null;
            for(Map.Entry<String, Column[]> entry:migration.getAlterColumn().entrySet()) {
                memoBuilder=new StringBuilder("MEMO:    ~:Forerign Key; A:AUTO INC; N:NOT NULL\n\n");
                mdDocBuilder.append(String.format(">> table: [%s](#%s) alter column to :\n\n",entry.getKey(),entry.getKey()));
                Column[] columns=entry.getValue();
                TableUtils.buildTableStruct(columns, mdDocBuilder, memoBuilder);
                mdDocBuilder.append(memoBuilder);
                mdDocBuilder.append("\n-------\n");
            }
        }
        mdDocBuilder.append("[-> Home](#自动生成库说明) \n");
    }

    public static void buildMakedownDoc(List<TableData> tableDataList, StringBuilder mdDocBuilder){
         for(TableData tableData:tableDataList)
             buildMakedownDoc(tableData,mdDocBuilder);
    }

    public static void buildMakedownDoc(TableData tableData, StringBuilder mdDocBuilder){
        mdDocBuilder.append(String.format("table data from : [%s](#%s) \n",tableData.getTable(),tableData.getTable()));
        List<TableData.GenerateColumn> generateColumns=tableData.getGenerateColumns();
        List<Row> rows=tableData.getDatas();
        if(generateColumns.size()>0){
            mdDocBuilder.append("\t\tauto generate column :\n");
            for(TableData.GenerateColumn generateColumn:generateColumns)
                mdDocBuilder.append((String.format("%s->%s\n",generateColumn.getColumn(),generateColumn.generator())));
            mdDocBuilder.append("-------\n");
        }
        if(rows.size()>0){
            mdDocBuilder.append("\n");
            mdDocBuilder.append("| index ");
            for(String columnName:tableData.getColumn())
                mdDocBuilder.append("| "+columnName+" ");
            mdDocBuilder.append("\n");
            mdDocBuilder.append("| -  ");
            for(String columnName:tableData.getColumn())
                mdDocBuilder.append("| - ");
            mdDocBuilder.append("\n");
            for(int i=0;i<rows.size();i++){
                mdDocBuilder.append("| "+i+" ");
                for(Object value:rows.get(i).getValue()) {
                    mdDocBuilder.append(String.format("| %s" , value == null ? "-" : value + " "));
                }
                mdDocBuilder.append("\n");
            }
            mdDocBuilder.append("\n-------\n");
        }
    }
}
